#include "board.h"
#include "cw32f030_systick.h"
#include "cw32f030_rcc.h"
#include "cw32f030_gpio.h"
#include "cw32f030_flash.h"

/******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
    printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}
#endif /* USE_FULL_ASSERT */

void board_init(void)
{
    RCC_HSE_Enable(RCC_HSE_MODE_OSC, 8000000, RCC_HSE_DRIVER_NORMAL, RCC_HSE_FLT_CLOSE); // 开启HSE时钟，HSE的频率范围为4MHz-32MHz

    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);

    RCC_PLL_Enable(RCC_PLLSOURCE_HSEOSC, 8000000, RCC_PLL_MUL_8); // 开启PLL，PLL输入为HSE

    RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_FLASH, ENABLE); // 使能FLASH时钟

    FLASH_SetLatency(FLASH_Latency_3);

    RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); // 切换系统时钟到PLL

    RCC_SystemCoreClockUpdate(CPU_FREQ); // 更新系统时钟频率

    RCC_PCLKPRS_Config(RCC_PCLK_DIV1); // 配置PCLK时钟分频

    // 初始化SysTick
    InitTick(CPU_FREQ);
}

void delay_us(unsigned long __us)
{
    uint32_t ticks;
    uint32_t told, tnow, tcnt = 38;

    // 计算需要的时钟数 = 延迟微秒数 * 每微秒的时钟数
    ticks = __us * (CPU_FREQ / 1000000);

    // 获取当前的SysTick值
    told = SysTick->VAL;

    while (1) {
        // 重复刷新获取当前的SysTick值
        tnow = SysTick->VAL;

        if (tnow != told) {
            if (tnow < told)
                tcnt += told - tnow;
            else
                tcnt += SysTick->LOAD - tnow + told;

            told = tnow;

            // 如果达到了需要的时钟数，就退出循环
            if (tcnt >= ticks)
                break;
        }
    }
}
// 搭配滴答定时器实现的精确ms延时
void delay_ms(unsigned long ms)
{
    delay_us(ms * 1000);
}

void delay_1us(unsigned long __us)
{
    delay_us(__us);
}
void delay_1ms(unsigned long ms)
{
    delay_ms(ms);
}